// ==UserScript==
// @name         ouchn auto watch
// @namespace    https://scriptcat.org/zh-CN/
// @version      0.1.0
// @description  开放大学自动看课
// @author       jjuker
// @match        *://lms.ouchn.cn/course/*
// ==/UserScript==

(function () {
    'use strict';

    const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
    const random = (max, min = 3000) => Math.floor(Math.random() * (max - min + 1)) + min;

    // 添加日志函数
    function log(message) {
        console.log(`[ouchn-auto-watch] ${message}`);
    }

    async function waitForElement(selector, timeout = 10000) {
        const start = Date.now();
        while (Date.now() - start < timeout) {
            const element = document.querySelector(selector);
            if (element) return element;
            await sleep(500);
        }
        throw new Error(`Element ${selector} not found`);
    }

    function setupHashChangeListener(callback) {
        let lastHash = location.hash;
        const observer = new MutationObserver(() => {
            if (lastHash !== location.hash) {
                lastHash = location.hash;
                callback();
            }
        });
        observer.observe(document, {
            subtree: true,
            childList: true,
            attributes: true,
            attributeFilter: ['href']
        });
        return observer;
    }

    async function getVideo() {
        try {
            return await waitForElement('.video-js .vjs-tech');
        } catch (e) {
            log('No video found, continuing');
            return null;
        }
    }

    async function playVideo(video) {
        return new Promise((resolve, reject) => {
            video.onended = resolve;
            video.onerror = () => {
                log(`Video error: ${video.error?.message}`);
                reject(video.error);
            };

            if (video.readyState >= 3) {  // HAVE_FUTURE_DATA
                video.play().catch(e => {
                    log(`Play failed: ${e.message}`);
                    reject(e);
                });
            } else {
                video.oncanplay = () => {
                    video.play().catch(e => {
                        log(`Play failed: ${e.message}`);
                        reject(e);
                    });
                };
            }
        });
    }

    async function nextPage() {
        try {
            log('Navigating to next page');
            const nextPageBtn = await waitForElement('button.next-btn.ivu-btn.ivu-btn-default');
            nextPageBtn.click();
        } catch (e) {
            log('No next page button found');
        }
    }


    let isRunning = false;
    async function main() {
        if (isRunning) {
            log('Script isRunning');
            return;
        }
        isRunning = true;
        log('Script started');

        try {
            log('Waiting');
            await sleep(5800);
            log('running');

            const video = await getVideo();
            if (video) {
                log('Video found, starting playback');
                await playVideo(video).catch(e => log(`Video playback error: ${e.message}`));
            }

            await sleep(random(15000, 5000));
            await nextPage();
            log('Script completed');
        } catch (e) {
            log(`Fatal error: ${e.message}`);
        } finally {
            log('Script finished');
            isRunning = false;
        }
    }

    // 启动
    let hashObserver;
    window.addEventListener('load', () => {
        main();
        hashObserver = setupHashChangeListener(() => {
            log('Page hash changed, restarting script');
            sleep(1000).then(() => {
                log('Restarting script');
                if (!isRunning) main();
            });
        });
    });

    // 卸载
    window.addEventListener('unload', () => {
        if (hashObserver) {
            hashObserver.disconnect();
        }
    });
})();